package com.yuebanmaoshare.file.config.security;

import com.yuebanmaoshare.file.config.security.entrypoint.JwtAuthenticationEntryPoint;
import com.yuebanmaoshare.file.config.security.filter.JwtAuthenticationTokenFilter;
import com.yuebanmaoshare.file.config.security.filter.UrlFilterInvocationSecurityMetadataSource;
import com.yuebanmaoshare.file.config.security.handle.JwtAccessDeniedHandler;
import com.yuebanmaoshare.file.config.security.manager.UrlAccessDecisionManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private JwtAuthenticationTokenFilter jwtRequestFilter;

    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    private UrlFilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource;

    @Autowired
    private UrlAccessDecisionManager urlAccessDecisionManager;

    // 使用安全的密码编码器替代已弃用的NoOpPasswordEncoder
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用 CSRF
                .csrf().disable()

                // 异常处理
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)
                .and()

                // 防止iframe跨域
                .headers().frameOptions().disable()
                .and()

                // 无状态会话
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()

                // 授权配置
                .authorizeRequests()
                // 静态资源
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/webSocket/**"
                ).permitAll()

                // Swagger
                .antMatchers("/swagger-ui.html", "/doc.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs", "/v3/api-docs/**").permitAll()

                // H2控制台
                .antMatchers("/h2-console").permitAll()
                .antMatchers("/h2-console/**").permitAll()

                // 文件访问
                .antMatchers(HttpMethod.GET, "/upload/**").permitAll()

                // Druid监控
                .antMatchers("/druid/**").permitAll()

                // OPTIONS请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                // 公共接口
                .antMatchers(
                        "/user/register",
                        "/user/login",
                        "/user/checkuserlogininfo",
                        "/filetransfer/downloadfile",
                        "/filetransfer/preview",
                        "/share/sharefileList",
                        "/share/sharetype",
                        "/share/checkextractioncode",
                        "/share/checkendtime",
                        "/notice/list",
                        "/error/**"
                ).permitAll()

                // 其他请求需要认证
                .anyRequest().authenticated()
                .and()

                // 添加自定义安全拦截器
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class);

        // 禁用缓存
        http.headers().cacheControl();

        return http.build();
    }

    /**
     * 自定义安全拦截器
     */
    @Bean
    public FilterSecurityInterceptor customFilterSecurityInterceptor() {
        FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
        interceptor.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource);
        interceptor.setAccessDecisionManager(urlAccessDecisionManager);
        return interceptor;
    }

    @Bean
    public InitializingBean initializingBean() {
        return () -> SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }
}